package org.epanetgrid.otimizacao.evaluators;

import java.util.List;

import org.epanetgrid.otimizacao.ag.SPMultiObjectiveFitness;
import org.epanetgrid.otimizacao.searchspace.IndividualEvaluator;
import org.epanetgrid.otimizacao.simulation.SimulacaoNaoConvergeException;
import org.jheuristics.Individual;
import org.jheuristics.ga.FitnessEvaluator;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;


/**
 * Avalia um indiv�duo retornando um SPMultiObjectiveFitness.
 *
 * @author Marcell Manfrin, marcell@ourgrid.org, Oct 31, 2005
 */
public class MultiObjectiveIndividualFitnessEvaluator implements FitnessEvaluator {
	private int[] objectives;
	private int indexPontoDeFalha;
	private int indexSeveridade;
	private int indexTipoMutacao;
	private IndividualEvaluator evaluator;

	/**
	 *
	 * @param objectives array contendo os indices de cada objetivo
	 * @param falha Index da falha no dataApplication dos indiv�duos
	 * @param severidade Index da severidade no dataApplication dos indiv�duos
	 * @param tipoDeMutacao Index do tipo de muta��o no dataApplication dos indiv�duos
	 */
	public MultiObjectiveIndividualFitnessEvaluator(int[] objectives, int falha, int severidade, int tipoDeMutacao) {
		this(null, objectives, falha, severidade, tipoDeMutacao);
	}

	/**
	 *
	 * @param evaluator respons�vel por setar o dataApplication no indiv�duo
	 * @param objectives array contendo os indices de cada objetivo
	 * @param falha Index da falha no dataApplication dos indiv�duos
	 * @param severidade Index da severidade no dataApplication dos indiv�duos
	 * @param tipoDeMutacao Index do tipo de muta��o no dataApplication dos indiv�duos
	 */
	public MultiObjectiveIndividualFitnessEvaluator(IndividualEvaluator evaluator, int[] objectives, int falha, int severidade, int tipoDeMutacao) {
		this.evaluator = evaluator;
		this.objectives = objectives;
		indexPontoDeFalha = falha;
		indexSeveridade = severidade;
		indexTipoMutacao = tipoDeMutacao;
	}

	/**
	 *
	 * @param individual
	 * @param population
	 * @param status
	 * @param config
	 * @return
	 * @see org.jheuristics.ga.FitnessEvaluator#evaluateFitness(org.jheuristics.Individual, org.jheuristics.ga.Population, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	public Comparable evaluateFitness(Individual individual, Population population, GAStatus status, GAConfig config) {
		if (null != evaluator) {
			Individual tmp = evaluator.evaluate(individual);
			individual.setDataApplication(tmp.getDataApplication());
		}
		
		List values = (List) individual.getDataApplication();
		
		if(values == null) {
			throw new SimulacaoNaoConvergeException("");
		}
		
		
		Comparable[] objectives = new Comparable[this.objectives.length];
		for (int i = 0; i < objectives.length; i++) {
			objectives[i] = (Comparable) values.get(this.objectives[i]);
		}
		int falha = ((Long) values.get(indexPontoDeFalha)).intValue();
		int severidade = ((Integer) values.get(indexSeveridade)).intValue();
		int tipoDeMutacao = ((Integer) values.get(indexTipoMutacao)).intValue();
		return new SPMultiObjectiveFitness(objectives, falha, severidade, tipoDeMutacao);
	}

}
